package common.core.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import okhttp3.*;
import okhttp3.FormBody.Builder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import javax.servlet.http.HttpServletRequest;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 工具类
 * @author LiuBo
 * 判断/验证,类型的方法用is开头
 * 转换类型的方法用 convert开头
 * 添加类型的方法用add开头
 * 获取类型的方法以get开头 
 * 设置类型的方法以set开头
 * 复制类型的用copy开头 
 * 排序类型的方法用sort开头
 * 功能性方法用execute开头
 */
@SuppressWarnings({"rawtypes","unchecked"})
public class CommonUtil {

	private static Logger log = LoggerFactory.getLogger(CommonUtil.class);

	public static final String PATH_PREPARED_STATEMENT_UUID = "\\{uuid\\}";// UUID路径占位符
	public static final String PATH_PREPARED_STATEMENT_DATE = "\\{date(\\(\\w+\\))?\\}";// 日期路径占位符
	public static final String COMMON_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
	/********功能性方法用execute开头*********/
	/**
	 * 字符串解密
	 * @param s
	 * @return
	 * @return?String
	 * @author add by chengxw
	 * @date 2013-5-31
	 */
	public static String executeDecrypt(String s){
		int iLen = 0;
		String sText =s;
		String sResult ="";
		//String sRtn = "";
		iLen = sText.length();
		for (int i =1;i <= iLen;i++){
			sResult =  (char)(sText.substring(i - 1, i ).codePointAt(0) - (2 * (iLen - i -2))) +sResult ;
		}
		return sResult;
	}

	/**
	 * 字符串加密
	 * @param str
	 * @return
	 * @return?String
	 * @author add by chengxw
	 * @date 2013-5-31
	 */
	public static String executeEncrypt(String str){
		StringBuffer resStr = new StringBuffer();
		StringBuffer buf = new StringBuffer(str.trim());
		buf = buf.reverse();//字符串翻转
		for (int i = 1; i <= buf.length(); i++) {
			char c = (char)(((buf.substring(i-1, i)).codePointAt(0))+((buf.length() - i - 2) * 2));
			resStr.append(c);
		}
		return resStr.toString();
	}
	public static void join(String before,Object append , String join){
		if(isEmpty(before)){
			before = append.toString() ;
		}else{
			before = before + join +append;
		}
	}
	public static void join(StringBuffer before,Object append , String join){
		if(isEmpty(before)){
			before.append(append);
		}else{
			before.append(join).append(append);
		}
	}
	/**JAVA 加密
	 * @param strSrc 需要加密人字符串，支持中文
	 *  	空位MD5，支持MD5 ,SHA-1 SHA-256
	 * @return?String
	 * @author add by x
	 * @date 2013-6-8
	 */
	public static String executeMD5(String strSrc) {
		return executeEncrypt(strSrc,null);
	}
	/**JAVA 加密
	 * @param strSrc 需要加密人字符串，支持中文
	 * @param encName  空位MD5，支持MD5 ,SHA-1 SHA-256
	 * @return?String
	 * @author add by x
	 * @date 2013-6-8
	 */
	public static String executeEncrypt(String strSrc, String encName) {
		MessageDigest md = null;
		String strDes = null;

		byte[] bt = strSrc.getBytes();
		try {
			if (encName == null || encName.equals("")) {
				encName = "MD5";
			}
			md = MessageDigest.getInstance(encName);
			md.update(bt);
			strDes = bytes2Hex(md.digest()); // to HexString
		} catch (NoSuchAlgorithmException e) {
			log.error("加密 失败",e);
			return null;
		}
		return strDes;
	}


	/***********排序类型的方法用sort开头**************/

	/**
	 * 对list中的数据按照字段field就进升序排序
	 * @param list
	 * @param field
	 */
	@SuppressWarnings("all")
	public static void sortAsc(List list,final String field){
		if (list == null){
			return;
		}
		Collections.sort(list,new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2){
				try {
					Object obj=null;
					Object obj2=null;
					if(o1 instanceof Map){
						obj=((Map)o1).get(field);
						if(CommonUtil.isEmpty(obj)){
							return -1;
						}
						obj2=((Map)o2).get(field);
						if(CommonUtil.isEmpty(obj2)){
							return 1;
						}	
					}else{
						obj=ReflectUtil.getFieldValue(o1, field);
						if(CommonUtil.isEmpty(obj)){
							return -1;
						}
						obj2=ReflectUtil.getFieldValue(o2, field);
						if(CommonUtil.isEmpty(obj2)){
							return 1;
						}	
					}	
					if(obj instanceof String){
						return ((String)obj).compareTo((String)obj2);
					}else if(obj instanceof Number){
						return ((Number)obj).longValue()-((Number)obj2).longValue()>0?1:-1;
					} else if(obj instanceof Date){
						return ((Date)obj).getTime()-((Date)obj2).getTime()>0?1:-1;
					}else{
						throw new Exception("字段数据类型只能是String,Number和Date");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return 0;
			}
		});
	}
	/**
	 * 对list中的数据按照字段field进行降序排序
	 * @param list
	 * @param field
	 */
	@SuppressWarnings("all")
	public static void sortDesc(List list,final String field){
		if (list == null){
			return;
		}
		Collections.sort(list,new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2){
				try {
					Object obj=null;
					Object obj2=null;
					if(o1 instanceof Map){
						obj=((Map)o1).get(field);
						if(CommonUtil.isEmpty(obj)){
							return 1;
						}
						obj2=((Map)o2).get(field);
						if(CommonUtil.isEmpty(obj2)){
							return -1;
						}	
					}else{
						obj=ReflectUtil.getFieldValue(o1, field);
						if(CommonUtil.isEmpty(obj)){
							return 1;
						}
						obj2=ReflectUtil.getFieldValue(o2, field);
						if(CommonUtil.isEmpty(obj2)){
							return -1;
						}	
					}
					if(obj instanceof String){
						return ((String)obj2).compareTo((String)obj);
					}else if(obj instanceof Number){
						return ((Number)obj2).longValue()-((Number)obj).longValue()>0?1:-1;
					} else if(obj instanceof Date){
						return ((Date)obj2).getTime()-((Date)obj).getTime()>0?1:-1;
					}else{
						throw new Exception("字段数据类型只能是String,Number和Date");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return 0;
			}
		});
	}
	/**
	 * 对list中的数据进行升序排序
	 * @param list
	 */
	@SuppressWarnings("all")
	public static void sortAsc(List list){
		if (isEmpty(list)){
			return;
		}
		Collections.sort(list,new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2){
				try {
					Object obj=o1;
					if(isEmpty(obj)){
						return -1;
					}
					Object obj2=o2;
					if(isEmpty(obj2)){
						return 1;
					}	
					if(obj instanceof String){
						return ((String)obj).compareTo((String)obj2);
					}else if(obj instanceof Number){
						return ((Number)obj).longValue()-((Number)obj2).longValue()>0?1:-1;
					} else if(obj instanceof Date){
						return ((Date)obj).getTime()-((Date)obj2).getTime()>0?1:-1;
					}else{
						throw new Exception("字段数据类型只能是String,Number和Date");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return 0;
			}
		});
	}

	/**
	 * 对list中的数据进行降序排序
	 * @param list
	 */
	@SuppressWarnings("all")
	public static void sortDesc(List list){
		if (isEmpty(list)){
			return;
		}
		Collections.sort(list,new Comparator<Object>() {
			@Override
			public int compare(Object o1, Object o2){
				try {
					Object obj=o1;
					if(isEmpty(obj)){
						return 1;
					}
					Object obj2=o2;
					if(isEmpty(obj2)){
						return -1;
					}	
					if(obj instanceof String){
						return ((String)obj2).compareTo((String)obj);
					}else if(obj instanceof Number){
						return ((Number)obj2).longValue()-((Number)obj).longValue()>0?1:-1;
					} else if(obj instanceof Date){
						return ((Date)obj2).getTime()-((Date)obj).getTime()>0?1:-1;
					}else{
						throw new Exception("字段数据类型只能是String,Number和Date");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return 0;
			}
		});
	}

	/*************** 复制类型的用copy开头 ******************/

	@SuppressWarnings("all")
	public static <T> List<T> copyListBean(List list_source,Class target_entity_class , String... ignores) {
		if(isEmpty(list_source)){
			return new ArrayList<T>();
		}
		List<T> ts=new ArrayList<T>();
		for(Object obj:list_source){
			T target;
			try {
				target = (T) target_entity_class.newInstance();
			} catch (Exception e) {
				log.error(e.getMessage(),e);
				target = null;
			}
			copyBean(obj, target,ignores);
			ts.add(target);
		}
		return ts;
	}


	public static <T> T copyBean(Object source, T t , String... ignores){
		T target;
		try {
			target= (T) t.getClass().newInstance();
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return null;
		}
		if(isEmpty(source)){
			return null;
		}
		try {
			copyBeanProperties(source, target,ignores);
		} catch (Exception e) {
			return null;
		}
		return target;
	}

	public static <T> T copyBean(Object source,Class<T> clazz,String... ignores){
		T target;
		try {
			target= (T) clazz.newInstance();
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return null;
		}
		if(isEmpty(source)){
			return null;
		}
		try {
			copyBeanProperties(source, target,null);
		} catch (Exception e) {
			return null;
		}
		return target;
	}
	public static <T> T copyBean(T source,String... ignores){
		T target;
		try {
			target= (T) source.getClass().newInstance();
		} catch (Exception e) {
			return null;
		}
		if(isEmpty(source)){
			return null;
		}
		try {
			copyBeanProperties(source, target,ignores);
		} catch (Exception e) {
			return null;
		}
		return target;
	}


	private static void copyBeanProperties(Object source, Object target, String[] ignores) throws Exception {
		Class<?> actualEditable = target.getClass();
		PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
		List<String> ignoreList = (ignores != null) ? Arrays.asList(ignores) : null;
		for (PropertyDescriptor targetPd : targetPds) {
			if (targetPd.getWriteMethod() != null &&
					(ignores == null || (!ignoreList.contains(targetPd.getName())))) {
				PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());
				if (sourcePd != null && sourcePd.getReadMethod() != null) {
					Method readMethod = sourcePd.getReadMethod();
					if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
						readMethod.setAccessible(true);
					}
					Object value = readMethod.invoke(source);
					Method writeMethod = targetPd.getWriteMethod();
					if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
						writeMethod.setAccessible(true);
					}
					String type = writeMethod.getParameterTypes()[0].getSimpleName();//参数类型
					if("boolean".equals(type)){
						boolean booleanVal = false;
						if("1".equals(value.toString())){
							booleanVal = true;
						}
						writeMethod.invoke(target, new Object[] { Boolean.valueOf(booleanVal) });
						continue;
					}
					if("Timestamp".equals(type)){
						if(CommonUtil.isNotEmpty(value)){
							Date date = (Date)value;
							Timestamp ts = new Timestamp(date.getTime());
							writeMethod.invoke(target, new Object[] { ts });
						}
						continue;
					}
					writeMethod.invoke(target, value);
				}
			}
		}
	}
	/********** 设置类型的方法以set开头 **************/




	/************* 获取类型的方法以get开头 ************/
	/**
	 * 将汉字转换为全拼
	 * 
	 * @param str
	 * @return String
	 */
	public static String getPinYin(String str){
		if(isEmpty(str)){
			return "";
		}
		return PinYinUtil.getPinYin(str);
	}
	/** 
	 * 清空STRINGBUFFER
	 * @param  sb
	 *
	 * @return void  
	 *
	 */  
	public static void getClearStringBuffer(StringBuffer sb){
		sb.delete(0, sb.length());
	}

	/**
	 * 对文件流输出下载的中文文件名进行编码 屏蔽各种浏览器版本的差异性
	 */
	public static String getChineseDownloadFileName(HttpServletRequest request, String pFileName) {
		String agent = request.getHeader("USER-AGENT");
		try {
			if (null != agent && -1 != agent.indexOf("MSIE")) {
				pFileName = URLEncoder.encode(pFileName, "utf-8");
			} else {
				pFileName = new String(pFileName.getBytes("utf-8"), "iso8859-1");
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return pFileName;
	}

	/**
	 * 根据日期获取星期
	 * 
	 * @param strdate
	 * @return
	 */
	public static String getWeekDayByDate(String strdate) {
		final String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-MM-dd");
		Calendar calendar = Calendar.getInstance();
		Date date = new Date();
		try {
			date = sdfInput.parse(strdate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		calendar.setTime(date);
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		if (dayOfWeek < 0)
			dayOfWeek = 0;
		return dayNames[dayOfWeek];
	}

	/** 
	 * 获得今天周几
	 *
	 * @return int   Calender.MONDAY 星期一  Calender.THURSDAY 星期二  ...
	 *
	 */  
	public static int getDayOfWeek(){
		return Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
	}

	/**
	 * 获得指定时间是周几
	 *
	 * @return int   Calender.MONDAY 星期一  Calender.THURSDAY 星期二  ...
	 */
	public static int getDayOfWeek(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.DAY_OF_WEEK);
	}

	/** 
	 * 获得随即颜色
	 * @return
	 * @author add by x@2012-10-30
	 * @return String  
	 *
	 */  
	public static String getRandom(int count){
		String S = "0123456789ABCDEF";
		Random r = new Random();
		String tmp ="";
		for (int i=0;i<count;i++){
			int index = r.nextInt(S.length());
			tmp += S.charAt(index);
		}
		return tmp;
	}

	/**
	 * 获得随机数字
	 * @param count  字符长度
	 * @return
	 */
	public static String getRandomNumber(int count) {
		String S = "0123456789";
		Random r = new Random();
		String tmp ="";
		for (int i=0;i<count;i++){
			int index = r.nextInt(S.length());
			tmp += S.charAt(index);
		}
		return tmp;
	}

	public static String getCurrentDateTime(){
		SimpleDateFormat format = new SimpleDateFormat(COMMON_DATE_FORMAT);
		return format.format(new Date(System.currentTimeMillis()));
	}

	public static String getCurrentDateTimeByFormat(String fmt){
		SimpleDateFormat format = new SimpleDateFormat(fmt);
		return format.format(new Date(System.currentTimeMillis()));
	}

	private static Map<String,SimpleDateFormat> dateFormatMap = new HashMap<>();
	public static String getDateFormat(Object date,String fmt){
		SimpleDateFormat format = dateFormatMap.get(fmt);
		if(isEmpty(format)){
			format = new SimpleDateFormat(fmt);
			dateFormatMap.put(fmt, format);
		}
		return format.format(date);
	}
	/**
	 * 随机获取UUID字符串(无中划线)
	 * 
	 * @return UUID字符串
	 */
	public static String getUUID() {
		String uuid = UUID.randomUUID().toString();
		return uuid.substring(0, 8) + uuid.substring(9, 13) + uuid.substring(14, 18) + uuid.substring(19, 23) + uuid.substring(24);
	}


	/**
	 * 描述
	 * @param date1  开始时间
	 * @param date2 结束时间
	 * @return  返回集合
	 * @author zhulc
	 * 2013-4-11 下午04:41:45
	 */
	@SuppressWarnings("static-access")
	public static List<String> getEndDate(Date date1,Date date2){
		List<String> list=new ArrayList<String>();
		Calendar cal1 = Calendar.getInstance();      
		cal1.setTime(date1);      
		Calendar cal2 = Calendar.getInstance();      
		cal2.setTime(date2);      
		long time1 = cal1.getTimeInMillis();                   	          
		long time2 = cal2.getTimeInMillis();           
		int  betweendays=(int) ((time2-time1)/(1000*3600*24));  
		cal1.add(cal1.DATE,1);	       	        
		SimpleDateFormat date=new SimpleDateFormat("yyyy-MM-dd");
		//  System.out.println("获取cal1:"+date.format(cal2.getTime()));	      
		for(int i=0;i<=betweendays;i++){
			Calendar caA = Calendar.getInstance();
			caA.setTime(date1);
			//System.out.println("i:"+i);
			//添加日期
			caA.add(cal2.DATE,i);
			Calendar cab = Calendar.getInstance();
			cab.setTime(caA.getTime());
			String week="";
			int weekDay=cab.get(cab.DAY_OF_WEEK)-1;
			switch (weekDay) {
			case 0:
				week="周日";
				break;
			case 1:
				week="周一";
				break;
			case 2:
				week="周二";
				break;
			case 3:
				week="周三";
				break;
			case 4:
				week="周四";
				break;
			case 5:
				week="周五";
				break;
			default:
				week="周六";
				break;
			}
			StringBuffer dates=new StringBuffer();
			dates.append(date.format(caA.getTime()));
			dates.append(" ");
			dates.append(week);
			list.add(dates.toString());
			//	System.out.println("获取天数"+date.format(caA.getTime()));
		}
		return list;
	}
	//获取MAC地址的方法  
	public static String getMACAddress(InetAddress ia)throws Exception{  
		//获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中。  
		byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();  
		//下面代码是把mac地址拼装成String  
		StringBuffer sb = new StringBuffer();  
		for(int i=0;i<mac.length;i++){  
			if(i!=0){  
				sb.append("-");  
			}  
			//mac[i] & 0xFF 是为了把byte转化为正整数  
			String s = Integer.toHexString(mac[i] & 0xFF);  
			sb.append(s.length()==1?0+s:s);  
		}  
		//把字符串所有小写字母改为大写成为正规的mac地址并返回  
		return sb.toString().toUpperCase();  
	}

	public static String getMAC(){
		String macAddress = "";
		try {
			InetAddress ia = InetAddress.getLocalHost();//获取本地IP对象  
			macAddress = getMACAddress(ia);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return macAddress;
	}
	/**
	 * getIntervalDays
	 * 两个日期间隔的天数
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static int getIntervalDays(Date startDate,Date endDate){
		int intervalDays = 0;
		Calendar calendarStartDate = Calendar.getInstance();
		Calendar calendarEndDate = Calendar.getInstance();
		calendarStartDate.setTime(startDate);
		calendarEndDate.setTime(endDate);
		//如果开始时间大于结束时间返回0
		if (calendarStartDate.after(calendarEndDate)) {
			return 0;
		}else {
			int intervalYears = calendarEndDate.get(Calendar.YEAR) - calendarStartDate.get(Calendar.YEAR);
			intervalDays = calendarEndDate.get(Calendar.DAY_OF_YEAR) - calendarStartDate.get(Calendar.DAY_OF_YEAR);
			for (int i = 0; i < intervalYears; i++) {
				calendarStartDate.set(Calendar.YEAR, (calendarStartDate.get(Calendar.YEAR) + 1));
				intervalDays += calendarStartDate.getMaximum(Calendar.DAY_OF_YEAR);
			}
			return intervalDays;
		}
	}


	/**
	 * 获取集合中对象的值转换成list并且返回
	 * @param collection
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static <E> List<E> getCollectionFieldToList(Collection collection,String key) {
		List<E> list=new ArrayList<E>();
		if (collection == null){
			return list;
		}else{
			try {
				for (Object t : collection) {
					if (t instanceof Map) {
						list.add((E)((Map)t).get(key));
					} else{//实体类
						list.add((E)getFieldValue(t, key));
					}
				}
			} catch (Exception e) {
				log.error(e.getMessage(),e);
				throw new CustomizeRuntimeException("获取集合对象属性["+key+"]失败",collection);
			}
		}
		return list;
	}

	/**
	 * 获取集合中对象的值转换成list并且返回
	 * @param collection
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static <K,E> Map<K,E> getCollectionFieldToMap(Collection collection,String key) {
		Map<K,E> result=new HashMap<K,E>();
		if (collection == null){
			return result;
		}else{
			try {
				for (Object t : collection) {
					if (t instanceof Map) {
						Map map = (Map)t;
						result.put((K)map.get(key),(E)t);
					} else{//实体类
						result.put((K)getFieldValue(t, key),(E)t);
					}
				}
			} catch (Exception e) {
				log.error(e.getMessage(),e);
				throw new CustomizeRuntimeException("获取集合对象属性["+key+"]失败",collection);
			}
		}
		return result;
	}

	/**
	 *
	 * @param collection
	 * @param key
	 * @param value
	 * @param <K>
	 * @param <E>
	 * @return
	 */
	public static <K,E> Map<K,E> getCollectionKVToMap(Collection collection,String key,String value) {
		Map<K,E> result=new HashMap<K,E>();
		if (collection == null){
			return result;
		}else{
			try {
				for (Object t : collection) {
					if (t instanceof Map) {
						Map map = (Map)t;
						result.put((K)map.get(key),(E)map.get(value));
					} else{//实体类
						result.put((K)getFieldValue(t, key),(E)getFieldValue(t, value));
					}
				}
			} catch (Exception e) {
				log.error(e.getMessage(),e);
				throw new CustomizeRuntimeException("获取集合对象属性["+key+"]失败",collection);
			}
		}
		return result;
	}
	/**
	 * 获取集合中对象的值转换成list并且返回
	 * @param collection
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static <K,E> Map<K,List<E>> getCollectionFieldToListObjectMap(Collection collection,String key) {
		Map<K,List<E>> result=new HashMap<K,List<E>>();
		if (collection == null){
			return result;
		}else{
			try {
				for (Object t : collection) {
					if (t instanceof Map) {
						Map map = (Map)t;
						List<E> list = result.get((K)map.get(key));
						if(isEmpty(list)){
							list = new ArrayList<E>();
						}
						list.add((E)t);
						result.put((K)map.get(key),list);
					} else{//实体类
						List<E> list = result.get((K)getFieldValue(t, key));
						if(isEmpty(list)){
							list = new ArrayList<E>();
						}
						list.add((E)t);
						result.put((K)getFieldValue(t, key),list);
					}
				}
			} catch (Exception e) {
				log.error(e.getMessage(),e);
				throw new CustomizeRuntimeException("获取集合对象属性["+key+"]失败",collection);
			}
		}
		return result;
	}
	/**
	 * 获取集合中对象的值转换成list并且返回
	 * @param collection
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static <E> Set<E> getCollectionFieldToSet(Collection collection,String key) {
		Set<E> list=new HashSet<E>();
		if (collection == null){
			return list;
		}else{
			try {
				for (Object t : collection) {
					if (t instanceof Map) {
						list.add((E)((Map)t).get(key));
					} else{//实体类
						list.add((E)getFieldValue(t, key));
					}
				}
			} catch (Exception e) {
				log.error(e.getMessage(),e);
				throw new CustomizeRuntimeException("获取集合对象属性["+key+"]失败",collection);
			}
		}
		return list;
	}
	/**
	 * 获取一个 heder+yyyyMMddHHmmssSSS+4位随机数
	 * @param heder
	 * @return
	 */
	public static String getBillNumber(String heder){
		return heder+new SimpleDateFormat("yyMMddHHmmssSSS").format(new Date())+getRandomNumber(4);
	}
	
	/**
	 * 
	 * @Title: generateDocumentNum 
	 * @Description: 生成单据号
	 * @param @param transNo 单据号类型  
	 * @param @param branchNo  操作员的所属门店
	 * @param @return    
	 * @return String    返回一个随机生成的单据号
	 * @throws
	 */
	public static String getSheetNo(String transNo,String branchNo){
		String documentId = transNo+getCurrentDateTimeByFormat("yyMMddHHmm")+getRandomNumber(6);
		return documentId;
	}

	/**
	 * <p>
	 * 反射对象获取泛型
	 * </p>
	 *
	 * @param clazz 对象
	 * @param index 泛型所在位置
	 * @return Class
	 */
	public static Class getSuperClassGenricType(final Class clazz, final int index) {
		Type genType = clazz.getGenericSuperclass();
		if (!(genType instanceof ParameterizedType)) {
			log.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName()));
			return Object.class;
		}
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
		if (index >= params.length || index < 0) {
			log.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index, clazz.getSimpleName(),
					params.length));
			return Object.class;
		}
		if (!(params[index] instanceof Class)) {
			log.warn(String.format("Warn: %s not set the actual class on superclass generic parameter", clazz.getSimpleName()));
			return Object.class;
		}
		return (Class) params[index];
	}

	/**
	 * <p>
	 * 获取该类的所有属性列表
	 * </p>
	 *
	 * @param clazz 反射类
	 * @return
	 */
	public static Map<String, Field> getFieldMap(Class<?> clazz) {
		List<Field> fieldList = getFieldList(clazz);
		Map<String, Field> fieldMap = Collections.emptyMap();
		if (isNotEmpty(fieldList)) {
			fieldMap = new LinkedHashMap<>();
			for (Field field : fieldList) {
				fieldMap.put(field.getName(), field);
			}
		}
		return fieldMap;
	}

	/**
	 * <p>
	 * 获取该类的所有属性列表
	 * </p>
	 *
	 * @param clazz 反射类
	 * @return
	 */
	public static List<Field> getFieldList(Class<?> clazz) {
		if (null == clazz) {
			return null;
		}
		List<Field> fieldList = new LinkedList<>();
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			/* 过滤静态属性 */
			if (Modifier.isStatic(field.getModifiers())) {
				continue;
			}
			/* 过滤 transient关键字修饰的属性 */
			if (Modifier.isTransient(field.getModifiers())) {
				continue;
			}
			fieldList.add(field);
		}
		/* 处理父类字段 */
		Class<?> superClass = clazz.getSuperclass();
		if (superClass.equals(Object.class)) {
			return fieldList;
		}
		/* 排除重载属性 */
		return excludeOverrideSuperField(fieldList, getFieldList(superClass));
	}

	/**
	 * <p>
	 * 排序重置父类属性
	 * </p>
	 *
	 * @param fieldList      子类属性
	 * @param superFieldList 父类属性
	 */
	public static List<Field> excludeOverrideSuperField(List<Field> fieldList, List<Field> superFieldList) {
		// 子类属性
		Map<String, Field> fieldMap = new HashMap<>();
		for (Field field : fieldList) {
			fieldMap.put(field.getName(), field);
		}
		for (Field superField : superFieldList) {
			if (null == fieldMap.get(superField.getName())) {
				// 加入重置父类属性
				fieldList.add(superField);
			}
		}
		return fieldList;
	}
	public static Object getClassDeclaredField(Object obj, String filedText) throws Exception {
		Field field = obj.getClass().getDeclaredField(filedText);
		if (field == null) {
			return null;
		}
		field.setAccessible(true);
		return field.get(obj);
	}


	public static <T> T getSuperclassDeclaredField(Object obj, String filedText) throws Exception {
		Field field = obj.getClass().getSuperclass().getDeclaredField(filedText);

		if (field == null) {
			return null;
		}

		field.setAccessible(true);
		return (T) field.get(obj);
	}

	/**
	 * 利用反射设置指定对象的指定属性为指定的值
	 * 
	 * @param obj 目标对象
	 * @param fieldName 目标属性
	 * @param fieldValue 目标值
	 */
	public static <T> void setFieldValue(Object obj, String fieldName, T fieldValue) {
		Field field = ReflectUtil.getField(obj, fieldName);
		if (field != null) {
			try {
				field.setAccessible(true);
				field.set(obj, fieldValue);
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}
	}

	/**
	 * 获取传入的对象,获取字段的值(getXXX)
	 * @param obj
	 * @param fieldName
	 * @return
	 */
	public static <T> T getFieldValue(Object obj, String fieldName) {
		Object result = null;
		Field field = ReflectUtil.getField(obj, fieldName);
		if (field != null) {
			field.setAccessible(true);
			try {
				result = field.get(obj);
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			}
		}
		return (T) result;
	}

	/**
	 * 向指定URL发送GET方法的请求
	 *
	 * @param host + address 发送请求的URL
	 * @param data 请求参数
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGetParamData(String host,String address, String data) {
		String url = null ;
		if(host.endsWith("/")||address.startsWith("/")) {
			url = host+address;
		}else {
			url = host+"/"+address;
		}
		return sendPostParamData(url, data);
	}
	public static String sendGetParamData(String url, String data) {
		try {
			OkHttpClient client = new OkHttpClient();
			if(CommonUtil.isNotEmpty(data)){
				url = url +"?data="+data;
			}

			Request request = new Request.Builder()
					.url(url)
					.build();
			Call call = client.newCall(request);
			Response response = call.execute();
			return response.body().string();
		} catch (Exception e) {
			log.error("GET 发送错误 url:{}",url,e);
			return CommonUtil.convertObjectToJson(Result.exception(e.getMessage()));
		}
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 *
	 * @param host +address 发送请求的 URL
	 * @param data  请求参数
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPostParamData(String host,String address, String data) {
		String url = null ;
		if(host.endsWith("/")||address.startsWith("/")) {
			url = host+address;
		}else {
			url = host+"/"+address;
		}
		return sendPostParamData(url, data);
	}
	public static String sendPostParamData(String url, String data) {
		try {
			OkHttpClient client = new OkHttpClient();
			
			RequestBody body = new Builder()
					.add("data", data)
					.build();

			Request request = new Request.Builder()
					.url(url)
					.post(body)
					.build();
			Call call = client.newCall(request);
			Response response = call.execute();
			return response.body().string();
		} catch (Exception e) {
			log.error("POST 发送错误 url:{}",url,e);
			return CommonUtil.convertObjectToJson(Result.exception(e.getMessage()));
		}
	}
	public static String sendPost(String url, Map<String, String> param) {
		OkHttpClient client = new OkHttpClient();
		Builder builder = new Builder();
		if(CommonUtil.isNotEmpty(param)) {
			for (String key:param.keySet()) {
				builder.add(key, param.get(key));
			}
		}
		Request request = new Request.Builder()
				.url(url)
				.post(builder.build())
				.build();
		try {
			Call call = client.newCall(request);
			return call.execute().body().string();
		} catch (Exception e) {
			log.error("post错误",e);
			return "{}";
		}
	}
	
	/********** 添加类型的方法用add开头 **********/
	/**
	 * 日期加一个月
	 * @param date 日期 格式
	 * @return
	 * @return?date
	 * @author add by jiaxj
	 * @date 2014-7-30
	 */
	public static Date addDateMonth(Date date,int months){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, months);
		return calendar.getTime();
	}
	/**
	 * 日期加天数
	 * @param date 日期 格式yyyy-mm-dd HH:mm:ss
	 * @param days 天数
	 * @return
	 * @return?String yyyy-mm-dd HH:mm:ss
	 * @author add by zlc
	 * @date 2013-12-10
	 */
	public static String addDate(String date,int days){
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
		try {
			Date da=format.parse(date);
			Calendar ca = Calendar.getInstance();  
			ca.setTime(da);   
			ca.add(Calendar.DATE,days);// 为增加的天数
			da = ca.getTime();  
			String backTime = format.format(da);  
			return backTime;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 添加一个元素到已有的数据里面去
	 * @param array
	 * @param element
	 * @return
	 */
	public static <T> T[] addArrayElement(T[] array, T element){
		Class type;
		if (array != null){
			type = array.getClass();
		} else if (element != null) {
			type = element.getClass();
		} else {
			type = Object.class;
		}
		T[] newArray = (T[])copyArrayGrow1(array, type);
		newArray[newArray.length - 1] = element;
		return newArray;
	}

	/*************** 转换类型的方法用 convert开头 *******************/

	public static List<Integer> convertStringToIntegerList(String... strs){
		if(isEmpty(strs)){
			return null;
		}else {
			List<Integer> list=new ArrayList<Integer>();
			for(String str:strs){
				list.add(Integer.valueOf(str));
			}
			return list;
		}
	}
	public static BigDecimal convertStringToBigDecimal(String str){
		if(isEmpty(str)){
			return BigDecimal.ZERO;
		}else{
			return new BigDecimal(str.trim());
		}
	}
	/**
	 * 将一个 Map 对象转化为一个 JavaBean
	 * @param clazz 要转化的类型
	 * @param map 包含属性值的 map
	 * @return 转化出来的 JavaBean 对象
	 * @throws IntrospectionException 如果分析类属性失败
	 * @throws IllegalAccessException 如果实例化 JavaBean 失败
	 * @throws InstantiationException 如果实例化 JavaBean 失败
	 * @throws InvocationTargetException 如果调用属性的 setter 方法失败
	 */
	public static <T> T convertMapToBean( Map map ,Class<T> clazz){
		if (map == null) {
			return null;    
		}  
		Object obj;
		try {
			obj = clazz.newInstance();
			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());    
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor property : propertyDescriptors) {  
				Method setter = property.getWriteMethod();
				try {
					if(setter!=null){
						Object object=map.get(property.getName());
						if(isNotEmpty(object)){
							setter.invoke(obj, object);
						} 
					}
				} catch (Exception e) {
					log.error(property.getName()+"["+map.get(property.getName()).getClass()+"]不能转换成-->"+property.getPropertyType());
					throw e;
				}
			}  
			return (T)obj;  
		} catch (Exception e) {
			log.error("Map --> Object 转换错误",e);
			return null;
		}  
	}
	/**
	 * format yyyy-MM-dd HH:mm:ss
	 * @param str
	 * @return
	 * @throws ParseException
	 */
	public static Date convertStringToDate(String str) throws ParseException{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String strDate = str;
		return sdf.parse(strDate);
	}
	/**
	 * format yyyy-MM-dd
	 * @param str
	 * @return
	 * @throws ParseException
	 */
	public static Date convertStringToOnlyDate(String str) throws ParseException{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String strDate = str;
		return sdf.parse(strDate);
	}
	/**
	 * @param str format
	 * @return
	 * @throws ParseException
	 */
	public static Date convertStringToDate(String str,String format) throws ParseException{
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		String strDate = str;
		return sdf.parse(strDate);
	}
	/**
	 * 将对象转换为JSON字符串
	 * @param object 对象
	 */
	public static String convertObjectToJson(Object object) {
		if(isEmpty(object)){
			return null;
		}
		try {
			return JSONObject.toJSONString(object);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
		return null;
	}

	public static String convertDateToString(Date date,String format){
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(date);
	}

	/**
	 * 将JSON字符串转换为对象
	 * @param json JSON字符串
	 * @param clazz 对象类型
	 */
	public static <T> T convertJsonToObject(String json, Class clazz,boolean isArray) {
		if(isEmpty(json)||isEmpty(clazz)){
			return null;
		}
		json = json.trim();
		if(json.startsWith("[")){
			if(isArray){
				return (T) JSONArray.parseArray(json,clazz).toArray((T[]) Array.newInstance(clazz, 0));
			}
			return (T) JSONArray.parseArray(json, clazz);
		}else if(json.startsWith("{")){
			return (T) JSONObject.parseObject(json, clazz);
		}

		return null;
	}
	/**
	 * 将JSON字符串转换为对象
	 * @param json JSON字符串
	 * @param clazz 对象类型
	 */
	public static <T> T convertJsonToObject(String json, Class clazz) {
		return convertJsonToObject(json, clazz,false);
	}

	/** 
	 * 将一个 JavaBean 对象转化为一个  Map 
	 * @param bean 要转化的JavaBean 对象 
	 * @return 转化出来的  Map 对象 
	 * @throws IntrospectionException 如果分析类属性失败 
	 * @throws IllegalAccessException 如果实例化 JavaBean 失败 
	 * @throws InvocationTargetException 如果调用属性的 setter 方法失败 
	 */   
	public static <T> Map<String,T> convertBeanToMap(Object bean){   
		try {
			if(isEmpty(bean)){
				return null;
			}
			Map returnMap = new HashMap();   
			Class type = bean.getClass();   
			BeanInfo beanInfo = Introspector.getBeanInfo(type);   
			PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();   
			for (int i = 0; i< propertyDescriptors.length; i++) {   
				PropertyDescriptor descriptor = propertyDescriptors[i];   
				String propertyName = descriptor.getName();   
				if (!propertyName.equals("class")) {   
					Method readMethod = descriptor.getReadMethod();   
					Object value = readMethod!=null ? readMethod.invoke(bean) : null;  
					returnMap.put(propertyName, value);     
				}   
			}   
			return returnMap;   
		} catch (Exception e) {
			log.error(bean.getClass().getName()+" to Map 转换错误 ,"+e.getMessage() , e);
			throw new CustomizeRuntimeException(bean.getClass().getName()+" to Map 转换错误");
		}
	} 
	public static List<Map<String,Object>> convertCollectionBeanToCollectionMap(Collection collections){   
		if(isEmpty(collections)){
			return null;
		}
		List<Map<String,Object>> list = new ArrayList<>();
		for(Object obj:collections){
			list.add(convertBeanToMap(obj));
		}
		return list;

	}

	

	/**
	 * 将驼峰数据转换为正常数据，去除_ 变大写
	 * BdItemInfo--->bd_item_info或者bdItemInfo--->bd_item_info
	 * @param map
	 * @return
	 */
	public static <V> Map<String,V> convertMapFieldToFistLowercaseHump(Map<String,V> map){
		if(isEmpty(map)){
			return map;
		}
		Map<String,V> result = new HashMap<String, V>();
		for(String key:map.keySet()){
			result.put(dbForDBToFistLowercaseHump((String)key), map.get(key));
		}
		return result;
	}
	public static <V> List<Map<String,V>> convertCollectionMapFieldToFistLowercaseHump(List<Map<String,V>> list){
		if(isEmpty(list)){
			return list;
		}
		List<Map<String,V>> result = new ArrayList<Map<String,V>>();
		for(Map<String,V> map:list){
			result.add(convertMapFieldToFistLowercaseHump(map));
		}
		return result;
	}

	/** 
	 * 把传入的字符串 转化成where xxx in (xxx) 的形式，
	 * @param str  1,2,3,4
	 * @return	('1','2','3','4')
	 * @author add by x@2012-9-17
	 * @return String  
	 *
	 */  
	public static String convertContainCommaStringToWhereIn(String str){
		if (str == null || "".equals(str)) return "('')";

		if (str.indexOf(",") > 0){
			String[] list= str.split(",");
			StringBuffer sb = new StringBuffer("(");
			for (int i=0;i<list.length;i++){
				sb.append("'"+list[i]+"'");
				if (i != list.length - 1){
					sb.append(",");
				}
			}
			sb.append(")");
			return sb.toString();
		}else{
			return "('"+str+"')";
		}
	}
	/******************  判断/验证,类型的方法用is开头  ********************/
	public static boolean isNotEmpty(Object obj) {
		return !isEmpty(obj);
	}

	public static boolean isEquals(Object a,Object b){
		if(isEmpty(a)){
			return false;
		}
		if(isEmpty(b)){
			return false;
		}
		if(a.equals(b)){
			return true;
		}
		return false;
	}

	public static <T> boolean isNotEquals(T a,T b){
		if(isEmpty(a)){
			return false;
		}
		if(isEmpty(b)){
			return false;
		}
		if(a.equals(b)){
			return false;
		}
		return true;
	}

	public static boolean isNotEqualsIntegerZero(Integer a){
		if(isEmpty(a)){
			return false;
		}
		if(a.equals(0)){
			return false;
		}
		return true;
	}
	public static boolean isEqualsIntegerZero(Integer a){
		if(isEmpty(a)){
			return false;
		}
		if(a.equals(0)){
			return true;
		}
		return false;
	}

	/**
	 * 判断对象是否Empty(null或元素为0)<br>
	 * 实用于对如下对象做判断:String Collection及其子类 Map及其子类
	 * 
	 * @param object
	 *            待检查对象
	 * @return boolean 返回的布尔值
	 */
	public static boolean isEmpty(Object object) {
		if (object == null){
			return true;
		} else if (object instanceof String) {
			if (StringUtils.isBlank((String)object)) {
				return true;
			}
		} else if (object instanceof Collection) {
			if (((Collection) object).size() == 0) {
				return true;
			}
		} else if (object instanceof Map) {
			if (((Map) object).size() == 0) {
				return true;
			}
		} else if(object instanceof StringBuffer){
			if (((StringBuffer) object).length() == 0) {
				return true;
			}
		} else if(object instanceof StringBuilder){
			if (((StringBuilder) object).length() == 0) {
				return true;
			}
		} else if(object.getClass().isArray()){
			if(Array.getLength(object)==0){
				return true;
			}
		} 

		return false;
	}
	/**
	 * 为数字类型
	 * @param obj
	 * @return
	 */
	public static Boolean isNumberForObject(Object obj){
		Boolean flag=false;
		if(obj instanceof Number){
			flag=true;
		}
		return flag;
	}
	/**
	 * 为数字类型
	 * @param obj
	 * @return
	 */
	public static Boolean isNotNumberForObject(Object obj){
		if(obj instanceof Number){
			return false;
		}
		return true;
	}
	/**
	 * 是否为时间类型
	 * @param obj
	 * @return
	 */
	public static Boolean isTimeForObject(Object obj){
		if(obj instanceof Date){
			return true;
		}
		return false;
	}
	/**
	 * 是否为数字类型
	 * @param clazz
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws Exception 
	 */
	public static Boolean isNumberForClass(Class clazz) {
		try {
			if(clazz.newInstance() instanceof Number){
				return true;
			}
		} catch (Exception e) {
			return false;
		} 
		return false;
	}
	/**
	 * 是否为日期类型
	 * @param clazz
	 * @return
	 * @throws Exception 
	 */
	public static Boolean isTimeForClass(Class clazz){
		try {
			if(clazz.newInstance() instanceof Date){
				return true;
			}
		} catch (Exception e) {
			return false;
		} 
		return false;
	}

	public static String isEmptyReturnNull(String param){
		return isEmpty(param)?null:param;
	}
	public static BigDecimal isEmptyReturnNull(BigDecimal param){
		return isEmpty(param)?null:param;
	}

	public static Object isEmptyReturnNull(Object param){
		return isEmpty(param)?null:param;
	}
	public static String isEmptyReturnEmpty(Object param){
		return isEmpty(param)?"":(String)param;
	}

	public static BigDecimal isEmptyReturnZero(BigDecimal param){
		return isEmpty(param)?BigDecimal.ZERO:param;
	}
	public static int isEmptyReturnZero(List param){
		return isEmpty(param)?0:param.size();
	}
	public static <T> T isEmptyReturn(T param, T returnValue){
		return isEmpty(param)?returnValue:param;
	}
	public static <T> T isEmptyReturn(Object IF,T empty, T notEmpty){
		return isEmpty(IF)?empty:notEmpty;
	}

	/*******私有方法区域*********/

	private static Object copyArrayGrow1(Object array, Class newArrayComponentType) {
		if (array != null) {
			int arrayLength = Array.getLength(array);
			Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
			System.arraycopy(array, 0, newArray, 0, arrayLength);
			return newArray;
		}
		return Array.newInstance(newArrayComponentType, 1);
	}

	private static String bytes2Hex(byte[] bts) {
		String des = "";
		String tmp = null;
		for (int i = 0; i < bts.length; i++) {
			tmp = (Integer.toHexString(bts[i] & 0xFF));
			if (tmp.length() == 1) {
				des += "0";
			}
			des += tmp;
		}
		return des;
	}

	public static boolean isIn(String object,Object...targets){
		if(isEmpty(object)||isEmpty(targets)||targets.length==0){
			return false;
		}
		for(Object obj:targets){
			if(object.equals(obj)){
				return true;
			}
		}
		return false;
	}
	/** 
	 * 获取访问者IP 
	 * 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。 
	 *  
	 * 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)， 
	 * 如果还不存在则调用Request .getRemoteAddr()。 
	 * @param request 
	 * @return 
	 */  
	public static String getIpAddr(HttpServletRequest request) {
		if(isEmpty(request)){
			return "";
		}
		String ip = request.getHeader("X-Real-IP");  
		if (ip!= null && !"".equals(ip) && !"unknown".equalsIgnoreCase(ip)) {  
			return ip;  
		}  
		ip = request.getHeader("X-Forwarded-For");  
		if (ip!= null && !"".equals(ip)  && !"unknown".equalsIgnoreCase(ip)) {  
			// 多次反向代理后会有多个IP值，第一个为真实IP。  
			int index = ip.indexOf(',');  
			if (index != -1) {  
				return ip.substring(0, index);  
			} else {  
				return ip;  
			}  
		} else {  
			return request.getRemoteAddr();  
		}  
	}  

	/** 
	 * 获取来访者的浏览器版本 
	 * @param request 
	 * @return 
	 */  
	public static String getRequestBrowserInfo(HttpServletRequest request){
		String browserVersion = null;  
		String header = request.getHeader("user-agent");  
		if(header == null || header.equals("")){  
			return "";  
		}  
		if(header.indexOf("MSIE")>0){  
			browserVersion = "IE";  
		}else if(header.indexOf("Firefox")>0){  
			browserVersion = "Firefox";  
		}else if(header.indexOf("Chrome")>0){  
			browserVersion = "Chrome";  
		}else if(header.indexOf("Safari")>0){  
			browserVersion = "Safari";  
		}else if(header.indexOf("Camino")>0){  
			browserVersion = "Camino";  
		}else if(header.indexOf("Konqueror")>0){  
			browserVersion = "Konqueror";  
		}  
		return browserVersion;  
	}  

	/** 
	 * 获取系统版本信息 
	 * @param request 
	 * @return 
	 */  
	public static String getRequestSystemInfo(HttpServletRequest request){
		String systenInfo = null;  
		String header = request.getHeader("user-agent");  
		if(header == null || header.equals("")){  
			return "";  
		}  
		//得到用户的操作系统  
		if (header.indexOf("NT 6.0") > 0){  
			systenInfo = "Windows Vista/Server 2008";  
		} else if (header.indexOf("NT 5.2") > 0){  
			systenInfo = "Windows Server 2003";  
		} else if (header.indexOf("NT 5.1") > 0){  
			systenInfo = "Windows XP";  
		} else if (header.indexOf("NT 6.0") > 0){  
			systenInfo = "Windows Vista";  
		} else if (header.indexOf("NT 6.1") > 0){  
			systenInfo = "Windows 7";  
		} else if (header.indexOf("NT 6.2") > 0){  
			systenInfo = "Windows Slate";  
		} else if (header.indexOf("NT 6.3") > 0){  
			systenInfo = "Windows 9";  
		} else if (header.indexOf("NT 5") > 0){  
			systenInfo = "Windows 2000";  
		} else if (header.indexOf("NT 4") > 0){  
			systenInfo = "Windows NT4";  
		} else if (header.indexOf("Me") > 0){  
			systenInfo = "Windows Me";  
		} else if (header.indexOf("98") > 0){  
			systenInfo = "Windows 98";  
		} else if (header.indexOf("95") > 0){  
			systenInfo = "Windows 95";  
		} else if (header.indexOf("Mac") > 0){  
			systenInfo = "Mac";  
		} else if (header.indexOf("Unix") > 0){  
			systenInfo = "UNIX";  
		} else if (header.indexOf("Linux") > 0){  
			systenInfo = "Linux";  
		} else if (header.indexOf("SunOS") > 0){  
			systenInfo = "SunOS";  
		}  
		return systenInfo;  
	}  

	/** 
	 * 获取来访者的主机名称 
	 * @param ip 
	 * @return 
	 */  
	public static String getHostName(String ip){  
		InetAddress inet;  
		try {  
			inet = InetAddress.getByName(ip);  
			return inet.getHostName();  
		} catch (UnknownHostException e) {  
			e.printStackTrace();  
		}  
		return "";  
	}   

	/** 
	 * 命令获取mac地址 
	 * @param cmd 
	 * @return 
	 */  
	private static String callCmd(String[] cmd) {  
		String result = "";  
		String line = "";  
		try {  
			Process proc = Runtime.getRuntime().exec(cmd);  
			InputStreamReader is = new InputStreamReader(proc.getInputStream());  
			BufferedReader br = new BufferedReader (is);  
			while ((line = br.readLine ()) != null) {  
				result += line;  
			}  
		}catch(Exception e) {  
			e.printStackTrace();  
		}  
		return result;  
	}  
	/** 
	 * 
	 * 
	 * 
	 * @param cmd 
	 *            第一个命令 
	 * 
	 * @param another 
	 *            第二个命令 
	 * 
	 * @return 第二个命令的执行结果 
	 * 
	 */  

	private static String callCmd(String[] cmd,String[] another) {  
		String result = "";  
		String line = "";  
		try {  
			Runtime rt = Runtime.getRuntime();  
			Process proc = rt.exec(cmd);  
			proc.waitFor(); // 已经执行完第一个命令，准备执行第二个命令  
			proc = rt.exec(another);  
			InputStreamReader is = new InputStreamReader(proc.getInputStream());  
			BufferedReader br = new BufferedReader (is);  
			while ((line = br.readLine ()) != null) {  
				result += line;  
			}  
		}catch(Exception e) {  
			e.printStackTrace();  
		}  
		return result;  
	}  

	/** 
	 * 
	 * 
	 * 
	 * @param ip 
	 *            目标ip,一般在局域网内 
	 * 
	 * @param sourceString 
	 *            命令处理的结果字符串 
	 * 
	 * @param macSeparator 
	 *            mac分隔符号 
	 * 
	 * @return mac地址，用上面的分隔符号表示 
	 * 
	 */  

	private static String filterMacAddress(final String ip, final String sourceString,final String macSeparator) {  
		String result = "";  
		String regExp = "((([0-9,A-F,a-f]{1,2}" + macSeparator + "){1,5})[0-9,A-F,a-f]{1,2})";  
		Pattern pattern = Pattern.compile(regExp);  
		Matcher matcher = pattern.matcher(sourceString);  
		while(matcher.find()){  
			result = matcher.group(1);  
			if(sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group(1))) {  
				break; // 如果有多个IP,只匹配本IP对应的Mac.  
			}  
		}  
		return result;  
	}  

	/** 
	 * @param ip 
	 *            目标ip 
	 * @return Mac Address 
	 * 
	 */  

	private static String getMacInWindows(final String ip){  
		String result = "";  
		String[] cmd = {"cmd","/c","ping " + ip};  
		String[] another = {"cmd","/c","arp -a"};  
		String cmdResult = callCmd(cmd,another);  
		result = filterMacAddress(ip,cmdResult,"-");  
		return result;  
	}  
	/** 
	 * 
	 * @param ip 
	 *            目标ip 
	 * @return Mac Address 
	 * 
	 */  
	private static String getMacInLinux(final String ip){   
		String result = "";   
		String[] cmd = {"/bin/sh","-c","ping " +  ip + " -c 2 && arp -a" };   
		String cmdResult = callCmd(cmd);   
		result = filterMacAddress(ip,cmdResult,":");   
		return result;   
	}   

	/** 
	 * 获取MAC地址 
	 * 
	 * @return 返回MAC地址 
	 */  
	public static String getMacAddress(String ip){  
		String macAddress = "";  
		macAddress = getMacInWindows(ip).trim();  
		if(macAddress==null||"".equals(macAddress)){  
			macAddress = getMacInLinux(ip).trim();  
		}  
		return macAddress;  
	}  

	/**
	 * 生成excel 文件
	 * @param dataRelation
	 * LinkedHashMap<String,String> relation = new LinkedHashMap<>();
	 *	relation.put("商品名称","productName");
	 * @param data
	 * @param path
	 */
	public static void createExcel(LinkedHashMap<String,String> dataRelation,List data,String path,String fileName,String sheetName){
		if(isEmpty(dataRelation)){
			throw CustomizeRuntimeException.exception("没有设置导出关系");
		}

		if(isEmpty(data)){
			throw CustomizeRuntimeException.exception("导出数据为空");
		}
		if(isEmpty(path)){
			throw CustomizeRuntimeException.exception("导出路径错误");
		}
		if(isEmpty(fileName)){
			throw CustomizeRuntimeException.exception("导出文件名错误");
		}
		WritableWorkbook wwb = null;
		OutputStream os = null;
		try {
			File folder=new File(path);
			if(!folder.exists() && !folder.isDirectory()){
				log.info("文件路径不存在: {}",path);
				folder.setReadable(true);
				folder.setExecutable(true);
				folder.setWritable(true);
				folder.mkdirs();
			}
			// 输出的excel的路径
			String filePath = path +fileName;
			File file=new File(filePath);
			if (!file.exists()) {//判断文件目录的存在
				file.setReadable(true);
				file.setExecutable(true);
				file.setWritable(true);
				file.createNewFile();
			}
			log.info("生成文件开始:{}",filePath);
			// 新建立一个jxl文件
			os = new FileOutputStream(filePath);
			// 创建Excel工作薄
			wwb = Workbook.createWorkbook(os);
			// 添加第一个工作表并设置第一个Sheet的名字
			WritableSheet sheet = wwb.createSheet(StringUtils.isBlank(sheetName)?"Sheet1":sheetName, 0);
			int lineIndex = 0;
			for(String title:dataRelation.keySet()){
				// Label(x,y,z) 代表单元格的第x+1列，第y+1行, 内容z
				// 在Label对象的子对象中指明单元格的位置和内容
				Label label = new Label(lineIndex , 0, title);
				// label = new Label(i, 0, title[i]);
				// 将定义好的单元格添加到工作表中
				sheet.addCell(label);
				lineIndex++;
			}

			for (int rowIndex = 0; rowIndex < data.size(); rowIndex++) {
				lineIndex = 0;//每一次都从第一行开始
				Object row = data.get(rowIndex);//当前行的数据
				for(String key:dataRelation.values()){
					Object line = null;
					if(row instanceof Map){
						line  = ((Map) row).get(key);
					}else{
						line = getFieldValue(row, key);
					}
					Label label = new Label(lineIndex , rowIndex +1, isEmptyReturnEmpty(line));
					sheet.addCell(label);
					lineIndex ++;
				}
			}
			log.info("生成文件结束:{}",filePath);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			throw CustomizeRuntimeException.exception("文件生成失败");
		}finally {
			try {
				os.flush();
				// 写入数据
				wwb.write();
				// 关闭文件
				wwb.close();
				os.close();
			} catch (Exception e2) {
				log.error(e2.getMessage(),e2);
			}
			
		}


	}
	
	/****************** 关 sql 和数据库打交道的 统一用 db 开头 ********************/
	/***
	 * @example null return null
	 * @example Integer 1 return 1
	 * @example String abc return 'abc'
	 * @example Date date return 'yyyy-MM-dd HH:mm:ss'
	 * @param obj 
	 * @return
	 */
	public static String dbGetSqlValueByObject(Object obj){
		if(isEmpty(obj)) {
			return null;
		}else if(isNumberForObject(obj)) {
			return obj.toString();
		}else if(isTimeForObject(obj)) {
			Date date=(Date) obj;
			String format = convertDateToString(date, "yyyy-MM-dd HH:mm:ss");
			return "'"+format+"'";
		}else {
			return "'"+obj+"'";
		}
	}
	/**
	 * @example c.BsIs-->c.bs_is
	 * @example abcD-->abc_d
	 * @example AbcD-->abc_d
	 * @param str
	 * @return
	 */
	public static String dbGetSqlFieldByClass(String str){
		if(str.contains(".")){
			str=str.split("\\.")[0]+"."+CommonUtil.dbHumpToDB(str.split("\\.")[1]);
		}else{
			str=CommonUtil.dbHumpToDB(str);
		}
		return str;
	}
	
	/**
	 * @example String return VARCHAR;
	 * @example BigDecimal return NUMERIC;
	 * ....
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	public static String dbJavaTypeToDbType(Class clazz) throws Exception{
		if(clazz.equals(String.class)){
			return "VARCHAR";
		}else if(clazz.equals(BigDecimal.class)){
			return "NUMERIC";
		}else if(clazz.equals(Boolean.class)||clazz.equals(boolean.class)){
			return "BIT";
		}else if(clazz.equals(Integer.class)||clazz.equals(int.class)){
			return "INTEGER";
		}else if(clazz.equals(Long.class)||clazz.equals(long.class)){
			return "BIGINT";
		}else if(clazz.equals(Float.class)||clazz.equals(float.class)){
			return "REAL";
		}else if(clazz.equals(Double.class)||clazz.equals(double.class)){
			return "DOUBLE";
		}else if(clazz.equals(Byte[].class)||clazz.equals(byte[].class)){
			return "VARBINARY";
		}else if(clazz.equals(java.sql.Date.class)||clazz.equals(Date.class)){
			return "TIMESTAMP";
		}else if(clazz.equals(Time.class)){
			return "TIMESTAMP";
		}else if(clazz.equals(Timestamp.class)){
			return "TIMESTAMP";
		}else{
			throw new Exception("java类--->"+clazz+"没有找到对应的数据库属性");
		}
	}
	/**
	 * @example CHAR return String.class
	 * @example CHAR return String.class
	 * @example VARCHAR return String.class
	 * @example NUMERIC return BigDecimal.class
	 * .....
	 * @return
	 * @throws Exception
	 */
	public static Class dbForDBTypeToJavaClass(String dbType) throws Exception{
		if(dbType.equals("CHAR")){
			return String.class;
		}else if(dbType.equals("VARCHAR")){
			return String.class;
		}else if(dbType.equals("LONGVARCHAR")){
			return String.class;
		}else if(dbType.equals("NUMERIC")){
			return BigDecimal.class;
		}else if(dbType.equals("DECIMAL")){
			return BigDecimal.class;
		}else if(dbType.equals("BIT")){
			return Boolean.class;
		}else if(dbType.equals("TINYINT")){
			return Byte.class;
		}else if(dbType.equals("SMALLINT")){
			return Short.class;
		}else if(dbType.equals("INTEGER")){
			return Integer.class;
		}else if(dbType.equals("BIGINT")){
			return Long.class;
		}else if(dbType.equals("REAL")){
			return Float.class;
		}else if(dbType.equals("FLOAT")){
			return Double.class;
		}else if(dbType.equals("DOUBLE")){
			return Double.class;
		}else if(dbType.equals("BINARY")){
			return Byte[].class;
		}else if(dbType.equals("VARBINARY")){
			return Byte[].class;
		}else if(dbType.equals("LONGVARBINARY")){
			return Byte[].class;
		}else if(dbType.equals("DATE")){
			return Date.class;
		}else if(dbType.equals("TIME")){
			return Date.class;
		}else if(dbType.equals("TIMESTAMP")){
			return Date.class;
		}else if(dbType.equals("DATETIME")){
			return Date.class;
		}else if(dbType.equals("INT")){
			return Integer.class;
		}else{
			throw new Exception("dbTypeToJava:数据库类型--->"+dbType+"没有找到对应的java类");
		}
	}
	/** 
	 * @example bd_item_info--->BdItemInfo
	 * @param 
	 * @return String  
	 *
	 */  
	public static String dbForDBToHump(String str){
		StringBuffer sb = new StringBuffer();
		String[] fields = str.split("_");
		String temp = null;
		for ( int i = 0 ; i < fields.length ; i++ ) {
			temp = fields[i].trim();
			sb.append(temp.substring(0, 1).toUpperCase()).append(temp.substring(1));
		}
		return sb.toString();
	}
	/**
	 * @example BdItemInfo--->bd_item_info或者bdItemInfo--->bd_item_info
	 * @param 
	 * @return
	 */
	public static String dbHumpToDB( String str ) {
		String first = str.substring(0,1).toLowerCase();
		String last =str.substring(1);
		StringBuilder tmp = new StringBuilder();
		for (int i=0;i<last.length();i++){
			if (Character.isUpperCase(last.charAt(i))){
				tmp.append("_"+last.substring(i, i+1).toLowerCase());
			}else{
				tmp.append(last.substring(i, i+1));
			}
		}
		return first+tmp.toString();
	}
	/** 
	 * @example bd_item_info--->bdItemInfo
	 * @param 
	 * @return String  
	 *
	 */  
	public static String dbForDBToFistLowercaseHump(String str){
		StringBuffer sb = new StringBuffer();
		String[] fields = str.split("_");
		String temp = null;
		for ( int i = 0 ; i < fields.length ; i++ ) {
			temp = fields[i].trim();
			if(i==0){
				sb.append(temp.substring(0, 1).toLowerCase()).append(temp.substring(1));
			}else{
				sb.append(temp.substring(0, 1).toUpperCase()).append(temp.substring(1));
			}
		}
		return sb.toString();
	}
	/**
	 * 验证这个类是否有长度
	 * @param dbType
	 * @return
	 * @throws Exception
	 */
	public static boolean isLengthForDb(String dbType) throws Exception{
		if(dbType.equals("CHAR")){
			return true;
		}else if(dbType.equals("VARCHAR")){
			return true;
		}else if(dbType.equals("LONGVARCHAR")){
			return true;
		}else if(dbType.equals("NUMERIC")){
			return true;
		}else if(dbType.equals("DECIMAL")){
			return true;
		}else if(dbType.equals("BIT")){
			return false;
		}else if(dbType.equals("TINYINT")){
			return true;
		}else if(dbType.equals("SMALLINT")){
			return true;
		}else if(dbType.equals("INTEGER")){
			return true;
		}else if(dbType.equals("BIGINT")){
			return true;
		}else if(dbType.equals("REAL")){
			return true;
		}else if(dbType.equals("FLOAT")){
			return true;
		}else if(dbType.equals("DOUBLE")){
			return true;
		}else if(dbType.equals("BINARY")){
			return false;
		}else if(dbType.equals("VARBINARY")){
			return false;
		}else if(dbType.equals("LONGVARBINARY")){
			return false;
		}else if(dbType.equals("DATE")){
			return false;
		}else if(dbType.equals("TIME")){
			return false;
		}else if(dbType.equals("TIMESTAMP")){
			return false;
		}else if(dbType.equals("DATETIME")){
			return false;
		}else if(dbType.equals("INT")){
			return true;
		}else{
			throw new Exception("checkLength:验证长度--->"+dbType+"没有找到对应的java类");
		}
	}
	/**
	 * 验证这个类是否有小数位
	 * @param dbType 数据库类型
	 * @return
	 * @throws Exception
	 */
	public static boolean dbFieldisDecimal(String dbType) throws Exception{
		if(dbType.equals("CHAR")){
			return false;
		}else if(dbType.equals("VARCHAR")){
			return false;
		}else if(dbType.equals("LONGVARCHAR")){
			return false;
		}else if(dbType.equals("NUMERIC")){
			return true;
		}else if(dbType.equals("DECIMAL")){
			return true;
		}else if(dbType.equals("BIT")){
			return false;
		}else if(dbType.equals("TINYINT")){
			return false;
		}else if(dbType.equals("SMALLINT")){
			return false;
		}else if(dbType.equals("INTEGER")){
			return false;
		}else if(dbType.equals("BIGINT")){
			return false;
		}else if(dbType.equals("REAL")){
			return false;
		}else if(dbType.equals("FLOAT")){
			return true;
		}else if(dbType.equals("DOUBLE")){
			return true;
		}else if(dbType.equals("BINARY")){
			return false;
		}else if(dbType.equals("VARBINARY")){
			return false;
		}else if(dbType.equals("LONGVARBINARY")){
			return false;
		}else if(dbType.equals("DATE")){
			return false;
		}else if(dbType.equals("TIME")){
			return false;
		}else if(dbType.equals("TIMESTAMP")){
			return false;
		}else if(dbType.equals("DATETIME")){
			return false;
		}else if(dbType.equals("INT")){
			return false;
		}else{
			throw new Exception("checkLength:验证长度--->"+dbType+"没有找到对应的java类");
		}
	}
}
